/*
 * This file is part of "Sorting Thoughts" project.
 *
 * Copyright (c) 2009 Hendrik Ebel
 * All Rights Reserved.
 *
 * Please visit http://code.google.com/p/sorting-thoughts/ for more information.
 *
 * --LICENSE NOTICE--
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
 * --LICENSE NOTICE--
 */
function OverviewAssistant(){
    this.firstCall = true;
    this.firstShake = true;
}

OverviewAssistant.prototype.setup = function(){
    Mojo.Log.info("#######################################");
    Mojo.Log.info("Setup overview scene");
    Mojo.Log.info("#######################################");
    
    if (SortingThoughts.isTouchPad()) {
        this.listAttributes = {
            itemTemplate: "overview/thoughtRowTemplateTouchpad",
            listTemplate: "overview/thoughtListTemplateTouchpad",
            filterFunction: this.searchList.bind(this),
            delay: 700,
            swipeToDelete: true,
            autoconfirmDelete: false,
            renderLimit: 400,
            initialAverageRowHeight: 20,
            reorderable: false
        };
    }
    else {
        this.listAttributes = {
            itemTemplate: "overview/thoughtRowTemplate",
            listTemplate: "overview/thoughtListTemplate",
            filterFunction: this.searchList.bind(this),
            delay: 700,
            swipeToDelete: true,
            autoconfirmDelete: false,
            renderLimit: 400,
            initialAverageRowHeight: 20,
            reorderable: false
        };
    }
    
    
    this.filter = "";
    this.thoughts = [];
    this.controller.setupWidget("overviewListWgt", this.listAttributes, this.thoughtModel = {
        items: this.thoughts
    });
    
    // add command menu
	if (SortingThoughts.isTouchPad()) {
		this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, {
	        items: [{
	            label: '',
	            command: 'newThought',
	            iconPath: 'images/menu-icon-new.png'
	        }, {
	            label: '',
	            command: 'searchThought',
	            icon: 'search'
	        }]
    	});
	} else {
		 this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, {
	        items: [{
	            label: '',
	            command: 'newThought',
	            iconPath: 'images/menu-icon-new.png'
	        }]
    	});
	}
   
    
    // add action handler
    this.selectThoughtHandler = this.selectThought.bindAsEventListener(this);
    this.listDeleteThoughtHandler = this.deleteThought.bindAsEventListener(this);
    
    // Setup App Menu 
    this.controller.setupWidget(Mojo.Menu.appMenu, SortingThoughts.MenuAttr, SortingThoughts.SortMenuModel);
    
    // Setup color selectors
    this.setupColorSelectors();
    
};

OverviewAssistant.prototype.handleShakingHandler = function(event){
    if (SortingThoughts.enableNewByShake && this.firstShake) {
        this.firstShake = false;
        Mojo.Log.info("Shake detected, open new thought scene...");
        this.openNewThought();
    }
};


OverviewAssistant.prototype.activate = function(event){
    Mojo.Log.info("#######################################");
    Mojo.Log.info("Overview activate");
    Mojo.Log.info("#######################################");
    if (typeof this.firstCall != 'undefined') {
        this.retrieveThoughtData();
    }
    
    this.firstShake = true;
    this.handleShakingHandler = this.handleShakingHandler.bindAsEventListener(this);
    Mojo.Event.listen(document, 'shaking', this.handleShakingHandler);
    
    this.controller.listen("overviewListWgt", Mojo.Event.listTap, this.selectThoughtHandler);
    this.controller.listen("overviewListWgt", Mojo.Event.listDelete, this.listDeleteThoughtHandler);
    this.controller.listen("overviewListWgt", Mojo.Event.propertyChange, this.colorSelectorChangedHandler);
    
    // Set Orientation to free to allow rotation 
    if (!SortingThoughts.isTouchPad() && this.controller.stageController.setWindowOrientation) {
        this.controller.stageController.setWindowOrientation("free");
    } 
	
	if (SortingThoughts.isTouchPad() && this.controller.stageController.setWindowOrientation) {
        this.controller.stageController.setWindowOrientation("right");
    }
	
    // set start orientation
    var appController = Mojo.Controller.getAppController();
    var orientation = appController.getScreenOrientation();
    
    this.orientationChanged(orientation);
    
    this.gotFilter = this.gotFilter.bind(this);
    Mojo.Event.listen(this.controller.get("overviewListWgt"), Mojo.Event.filter, this.gotFilter, true);
    
};

OverviewAssistant.prototype.deactivate = function(event){
    Mojo.Log.info("#######################################");
    Mojo.Log.info("Overview deactivate");
    Mojo.Log.info("#######################################");
    this.controller.stopListening("overviewListWgt", Mojo.Event.listDelete, this.listDeleteThoughtHandler);
    this.controller.stopListening("overviewListWgt", Mojo.Event.listTap, this.selectThoughtHandler);
    this.controller.stopListening("overviewListWgt", Mojo.Event.propertyChange, this.colorSelectorChangedHandler);
    Mojo.Event.stopListening(document, 'shaking', this.handleShakingHandler);
    Mojo.Event.stopListening(this.controller.get("overviewListWgt"), Mojo.Event.filter, this.gotFilter, true);
};

OverviewAssistant.prototype.cleanup = function(event){
    Mojo.Log.info("#######################################");
    Mojo.Log.info("Overview cleanup");
    Mojo.Log.info("#######################################");
    this.controller.stopListening(this.controller.stageController.document, 'shaking', this.handleShakingHandler.bindAsEventListener(this));
}

/*
 * Setup the color selector.
 */
OverviewAssistant.prototype.setupColorSelectors = function(){

    this.colorSelections = [{
        label: $L('White'),
        value: "whiteColor",
        secondaryIcon: 'whiteColorIcon'
    }, {
        label: $L('Orange'),
        value: "orangeColor",
        secondaryIcon: 'orangeColorIcon'
    }, {
        label: $L('Yellow'),
        value: "yellowColor",
        secondaryIcon: 'yellowColorIcon'
    }, {
        label: $L('Green'),
        value: "greenColor",
        secondaryIcon: 'greenColorIcon'
    }, {
        label: $L('Cyan'),
        value: "cyanColor",
        secondaryIcon: 'cyanColorIcon'
    }, {
        label: $L('Blue'),
        value: "blueColor",
        secondaryIcon: 'blueColorIcon'
    }, {
        label: $L('Pink'),
        value: "pinkColor",
        secondaryIcon: 'pinkColorIcon'
    }, {
        label: $L('Magenta'),
        value: "magentaColor",
        secondaryIcon: 'magentaColorIcon'
    }, {
        label: $L('Red'),
        value: "redColor",
        secondaryIcon: 'redColorIcon'
    }, {
        label: $L('Strike'),
        value: "strikeColor",
        secondaryIcon: 'strikeColorIcon'
    }];
    
    this.controller.setupWidget('highlighter', {
        label: '',
        choices: this.colorSelections,
        modelProperty: 'colorStyleChange'
    });
    // Observe mojo-property-change events on the selector widgets:
    this.colorSelectorChangedHandler = this.colorSelectorChanged.bindAsEventListener(this);
    
};

/*
 * Handle color selector changes.
 */
OverviewAssistant.prototype.colorSelectorChanged = function(event){
    // Mojo.Log.info("Handle propertyChange event: " + Object.toJSON(event));
    // handle only color changes
    if (event.property === 'colorStyleChange') {
        // set new style in model
        event.model.thought.rowStyle = event.value;
        
        // update thought in DB
        this.updateRowColor(event.value, event.model.thought.id);
        
        // update model
        this.controller.modelChanged(this.thoughtModel, this);
    }
};

/*
 * Handle orientation changes.
 */
OverviewAssistant.prototype.orientationChanged = function(orientation){

    Mojo.Log.info("orientation is: " + orientation);
    
    if (SortingThoughts.isTouchPad()) {
    
        // wide
        Mojo.Log.info("TouchPad: set style wide");
        // double check, not sure was is set first
        $('headerDiv').removeClassName("header");
        $('headerDiv').addClassName("headerTouchPadWide");
        
   	 	$('thoughtEntries').removeClassName("thoughtEntriesStyle");
        $('thoughtEntries').addClassName("thoughtEntriesStyleTouchPadWide");
        
        $('footerDiv').removeClassName("footer");
        $('footerDiv').addClassName("footerTouchpadWide");
        
        if (!SortingThoughts.showDate) {
            this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateTouchpadWideWithoutDate';
        }
        else {
            this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateTouchpadWide';
        }
        
        this.listAttributes.swipeToDelete = true;
        this.listAttributes.autoconfirmDelete = false;
        
    } else {
    	// only for pre, pixi, veer
    	var headerStyleWide = "headerWide";
	    var thoughtEntriesStyleWide = "thoughtEntriesWide";
	    var footerStyleWide = "footerWide";
	    
	    // set special styles for pixi/veer
	    if (Mojo.Environment.DeviceInfo.touchableRows < 8) {
	        headerStyleWide = "headerWidePixi";
	        footerStyleWide = "footerWidePixi";
	        thoughtEntriesStyleWide = "thoughtEntriesWidePixi";
	    }
	
        if (orientation == 'left' || orientation == 'right') {
            $('thoughtEntries').removeClassName("thoughtEntriesStyle");
            $('thoughtEntries').addClassName(thoughtEntriesStyleWide);
            
            $('headerDiv').removeClassName("header");
            $('headerDiv').addClassName(headerStyleWide);
            
            $('footerDiv').removeClassName("footer");
            $('footerDiv').addClassName(footerStyleWide);
            
            if (!SortingThoughts.showDate) {
                if (Mojo.Environment.DeviceInfo.touchableRows < 8) {
                    this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateWithoutDateWidePixi';
                }
                else {
                    this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateWithoutDateWide';
                }
            }
            else {
                if (Mojo.Environment.DeviceInfo.touchableRows < 8) {
                    this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateWidePixi';
                }
                else {
                    this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateWide';
                }
            }
            
            // support no delete in wide view
            this.listAttributes.swipeToDelete = false;
        } else {
            $('thoughtEntries').removeClassName(thoughtEntriesStyleWide);
            $('thoughtEntries').addClassName("thoughtEntriesStyle");
            
            $('headerDiv').removeClassName(headerStyleWide);
            $('headerDiv').addClassName("header");
            
            $('footerDiv').removeClassName(footerStyleWide);
            $('footerDiv').addClassName("footer");
            
            
            if (!SortingThoughts.showDate) {
                this.listAttributes.itemTemplate = 'overview/thoughtRowTemplateWithoutDate';
            }
            else {
                this.listAttributes.itemTemplate = 'overview/thoughtRowTemplate';
            }
            
            this.listAttributes.swipeToDelete = true;
            this.listAttributes.autoconfirmDelete = false;
        }
    }
    
    // update model
    this.controller.modelChanged(this.thoughtModel, this);
};

OverviewAssistant.prototype.gotFilter = function(event){
    this.filter = event.filterString;
};

/*
 * Search in thought list
 */
OverviewAssistant.prototype.searchList = function(filterString, listWidget, offset, count){
    Mojo.Log.info("Search list asked for items: filter=", filterString, " offset=", offset, " limit=", count);
    
    var subset = [];
    var totalSubsetSize = 0;
    
    // If search string is null, return empty list, otherwise build results list 
    if (filterString !== "") {
        this.filter = filterString;
        // Search database for stories with the search string; push matches 
        var items = [];
        // Comparison function for matching strings in next for loop 
        var hasString = function(filterStr, thought){
            var upperCasefilterStr = filterStr.toUpperCase();
            if (thought.title.toUpperCase().indexOf(upperCasefilterStr) >= 0) {
                return true;
            }
            
            if (thought.content.toUpperCase().indexOf(upperCasefilterStr) >= 0) {
                return true;
            }
            
            return false;
        };
        
        // find relevant thoughts
        for (var i = 0; i < this.thoughts.length; i++) {
            // Mojo.Log.info("Check thought: ", Object.toJSON(this.thoughts[i]));
            if (hasString(filterString, this.thoughts[i].thought)) {
                var thought = this.thoughts[i];
                items.push(thought);
            }
        }
        
        var entireList = items;
        
        // Cut down list results to just the window asked for by the widget 
        var cursor = 0;
        while (true) {
            if (cursor >= entireList.length) {
                break;
            }
            
            if (subset.length < count && totalSubsetSize >= offset) {
                subset.push(entireList[cursor]);
            }
            totalSubsetSize++;
            cursor++;
        }
        
        listWidget.mojo.setLength(totalSubsetSize);
        listWidget.mojo.setCount(totalSubsetSize);
        
    }
    else {
        // set all thoughts
        subset = this.thoughts;
    }
    
    // set exist filter string
    var searchTermElement = this.controller.get("thoughtListMain").getElementsByClassName('search-term');
    if (filterString !== "" && searchTermElement != null && searchTermElement.length == 1) {
        searchTermElement[0].innerHTML = this.filter;
        Mojo.Log.info("update filter string");
    }
    
    listWidget.mojo.noticeUpdatedItems(offset, subset);
};


OverviewAssistant.prototype.selectThought = function(event){
    Mojo.Controller.stageController.pushScene({
        transition: Mojo.Transition.zoom,
        name: "edit"
    }, event.item.thought, false);
};

OverviewAssistant.prototype.handleCommand = function(event){
    if (event.type == Mojo.Event.command) {
        switch (event.command) {
            case 'newThought':
                this.openNewThought();
                break;
			case 'searchThought':
				var filterField = this.controller.get("thoughtListMain").down("div[x-mojo-element=FilterField]");
				filterFieldAsst = filterField._mojoController.assistant;
				if (filterFieldAsst.filterOpen) {
					filterField.mojo.close();
				}
				else {
					filterField.mojo.open();
				}
				break;
        }
    }
};

OverviewAssistant.prototype.openNewThought = function(){

    /*
     // only for testing
     for (var i = 0; i < 10; i++) {
     SortingThoughts.dao.insertTestContent(i);
     SortingThoughts.dao.insertTestContent.delay(10);
     }
     */
    var thought = SortingThoughts.dao.insertNewThought();
    if (this.filter.length > 0) {
        thought.title = this.filter;
    }
    
    Mojo.Controller.stageController.pushScene({
        transition: Mojo.Transition.zoom,
        name: "edit"
    }, thought, true);
};

// ######### delete ###########

OverviewAssistant.prototype.deleteThought = function(event){
    SortingThoughts.dao.deleteThought(event.item.thought.id);
    // refresh thought list
    this.retrieveThoughtData();
};

// ######### update ###########

OverviewAssistant.prototype.updateRowColor = function(rowStyle, thoughtId){
    SortingThoughts.dao.updateRowStyle(rowStyle, thoughtId);
};

// ######### select ###########

OverviewAssistant.prototype.retrieveThoughtData = function(){

    if (!SortingThoughts.dao.db) {
        Mojo.Log.error("Could not access sorting thoughts database");
    }
    else {
        // default sorting order (by creation date)
        var sql = "SELECT * FROM 'thought' ORDER BY createDate DESC";
        
        if (SortingThoughts.sortByTitle) {
            sql = "SELECT * FROM 'thought' ORDER BY UPPER(title) ASC";
        }
        else 
            if (SortingThoughts.sortByMdate) {
                sql = "SELECT * FROM 'thought' ORDER BY modifiedDate DESC";
            }
            else 
                if (SortingThoughts.sortByColor) {
                    sql = "SELECT * FROM 'thought' ORDER BY rowStyle ASC, UPPER(title) ASC";
                }
                else 
                    if (SortingThoughts.sortByVdate) {
                        sql = "SELECT * FROM 'thought' ORDER BY lastViewedDate DESC";
                    }
        
        SortingThoughts.dao.db.transaction((function(transaction){
            transaction.executeSql(sql, [], this.selectQueryDataHandler.bind(this), this.dbErrorHandler.bind(this));
        }).bind(this));
    }
};

OverviewAssistant.prototype.selectQueryDataHandler = function(transaction, results){
    try {
        var list = [];
        for (var i = 0; i < results.rows.length; i++) {
            var row = results.rows.item(i);
            var title = row['title'];
            var content = row['content'];
            var id = row['id'];
            var mDate = row['modifiedDate'];
            var vDate = row['lastViewedDate'];
            var cDate = row['createDate'];
            var sDate = row['lastSyncDate'];
            var fav = row['favorite'];
            var style = row['rowStyle'];
            var imported = row['imported'];
            
            var thought = new Thought(id, title, content, mDate, vDate, cDate, sDate, imported, fav, style);
            
            list.push({
                thought: thought
            });
        }
        //update the list widget
        this.thoughts.clear();
        Object.extend(this.thoughts, list);
        this.controller.modelChanged(this.thoughtModel, this);
    } 
    catch (e) {
        Mojo.Log.error("Could not read DB results: " + error.message);
    }
};

// ######### success and error handler ###########

OverviewAssistant.prototype.dbSuccessHandler = function(transaction, results){
    Mojo.Log.info("Successfully SQL execution");
};

OverviewAssistant.prototype.dbErrorHandler = function(transaction, error){
    Mojo.Log.error("Could not execute SQL: " + error.message);
    
    // if an error occurred is the DB update broken or ignored (maybe a reset without cookie deletion) 
    if (!SortingThoughts.dbErrorDetected) {
        SortingThoughts.dbErrorDetected = true;
        // 2nd change the setup DB
        Mojo.Controller.stageController.popScene("overview");
        Mojo.Controller.stageController.pushScene("start");
    }
    else {
        var errorMsg = $L('Oh no! An error is occurred. Please contact the developer with following error message: ') + error.message;
        Mojo.Controller.errorDialog(errorMsg, this.controller.window);
    }
    
};

OverviewAssistant.prototype.dbInsertErrorHandler = function(transaction, error){
    Mojo.Log.error("Could not insert data in Sorting Thoughts DB: " + error.message);
    Mojo.Controller.errorDialog(error.message, this.controller.window);
};


